/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	ViewDomain.java
 * 模块说明：	
 * 修改历史：
 * 2006-6-22 - lxm - 创建。
 */
package com.hd123.rumba.action.domain;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.HibernateException;

import com.hd123.rumba.action.log.ViewEntityLogs;
import com.hd123.rumba.action.organization.ViewOrganization;
import com.hd123.rumba.action.user.ViewRole;
import com.hd123.rumba.action.user.ViewUser;
import com.hd123.rumba.cartridge.CCartFunctionView;
import com.hd123.rumba.cartridge.biz.BCartFunctionView;
import com.hd123.rumba.cartridge.biz.BCartridge;
import com.hd123.rumba.cartridge.biz.IBCartridgeMgr;
import com.hd123.rumba.cartridge.biz.SCartFunctionView;
import com.hd123.rumba.domain.CDomain;
import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.domain.IDomainMgr;
import com.hd123.rumba.domain.biz.BDomain;
import com.hd123.rumba.domain.biz.IBDomainMgr;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.log.ActionLogger;
import com.hd123.rumba.log.RumbaLogger;
import com.hd123.rumba.organization.biz.IBOrganizationMgr;
import com.hd123.rumba.organization.biz.SOrganization;
import com.hd123.rumba.request.Action;
import com.hd123.rumba.request.ActionAbstractImpl;
import com.hd123.rumba.request.ActionConstants;
import com.hd123.rumba.request.JspLib;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.backprocess.BackProcessPool;
import com.hd123.rumba.sql.biz.BResultPage;
import com.hd123.rumba.sql.biz.BSQLSubquery;
import com.hd123.rumba.user.IPermissionMgr;

/**
 * 域 | Action | 基类
 * 
 * @author lxm
 * 
 */
public abstract class BaseViewDomain extends ActionAbstractImpl {

  RumbaLogger debugLogger = RumbaLogger.getLogger(this.getClass());
  
  /* Templates */
  protected static final String TEMPLATE_LIST = "domain/DomainsList.jsp";
  protected static final String TEMPLATE_FILTER = "domain/DomainsFilter.jsp";
  protected static final String TEMPLATE_VIEW = "domain/DomainView.jsp";
  protected static final String TEMPLATE_BROWSERDEF = "domain/DomainBrowserDef.jsp";
  protected static final String TEMPLATE_LOADCFV_1 = "domain/LoadCFV_1.jsp";
  protected static final String TEMPLATE_LOADCFV_2 = "domain/LoadCFV_2.jsp";
  protected static final String TEMPLATE_LOADCFV_DOING = "domain/LoadCFV_Doing.jsp";
  protected static final String TEMPLATE_UNLOADCFV_1 = "domain/UnloadCFV_1.jsp";
  protected static final String TEMPLATE_UNLOADCFV_DOING = "domain/UnloadCFV_Doing.jsp";

  private static final String EVENT_LOADCFV = "装载" + CCartFunctionView.CAPTION_CLASS;
  private static final String EVENT_UNLOADCFV = "卸载" + CCartFunctionView.CAPTION_CLASS;

  public String list() throws Exception {
    logger.info(ActionLogger.EVENT_LIST, null);

    DomainFilter filter = getFormFilter();
    Boolean isRecycle = Boolean.FALSE;
    return this.showList(filter, isRecycle);
  }

  public String listRecycle() throws Exception {
    logger.info(ActionLogger.EVENT_LIST, null);

    DomainFilter filter = getFormFilter();
    Boolean isRecycle = Boolean.TRUE;
    return this.showList(filter, isRecycle);
  }

  public String filter() throws Exception {
    DomainFilter filter = getFormFilter();
    String isRecycleStr = (String) dd.getFormValue("isRecycle");
    if (isRecycleStr == null)
      isRecycleStr = "FALSE";
    Boolean isRecycle = "TRUE".equalsIgnoreCase(isRecycleStr) ? Boolean.TRUE : Boolean.FALSE;

    dd.put("filter", filter);
    dd.put("isRecycle", isRecycle);
    dd.setWorkingTemplate(TEMPLATE_FILTER);
    return ActionConstants.APPLICATIONFRAME;
  }

  public String view() throws Exception {
    logger.info(ActionLogger.EVENT_VIEW, null);

    String uuid = (String) dd.getFormValue("domain_uuid");
    if (uuid == null)
      throw new Exception("缺少必须的参数domain_uuid。");
    String tabView = (String) dd.getFormValue("tabView");
    if (tabView == null)
      tabView = "tvFuncViews";

    BDomain domain = getBDomainMgr().loadDomain(uuid);

    dd.put("tabView", tabView);
    dd.put("entriesValidation", this.getEntriesValidation(uuid, domain.getCode()));
    return showDetail(domain, JspLib.VALUE_FORMSTATE_VIEW);
  }

  public String viewOrganization() throws Exception {
    String uuid = (String) dd.getFormValue("domain_uuid");
    if (uuid == null)
      throw new Exception("缺少必须的参数domain_uuid。");

    IBOrganizationMgr orgMgr = (IBOrganizationMgr) NamingMgr.getInstance().lookupMgr(
        IBOrganizationMgr.class);
    SOrganization org = (SOrganization) orgMgr
        .getOrganizationByOrgDomain(uuid, SOrganization.class);
    if (org == null)
      throw new Exception("当前域没有对应的组织。");

    dd.putFormValue("start", "view");
    dd.putFormValue("org_uuid", org.getUuid());

    Action a = new ViewOrganization();
    a.init(dd);
    return a.execute();
  }

  public String browse() throws Exception {
    dd.put("entityCaption", CDomain.CAPTION_CLASS);
    dd.put("entityIcon", "rumba/images/domain/domain_small.gif");
    dd.setWorkingTemplate(TEMPLATE_BROWSERDEF);
    return ActionConstants.BROWSERFRAME;
  }

  public String loadFuncView() throws Exception {
    String step = (String) dd.getFormValue("step");
    if (step == null)
      step = "1";
    String uuid = (String) dd.getFormValue("domain_uuid");
    if (uuid == null)
      throw new Exception("缺少必须的参数domain_uuid。");

    String[] ownerKeys = new String[] {
        this.getCurrentUser().getUuid(), uuid };
    ProcessLoadCFV process = (ProcessLoadCFV) BackProcessPool.getInstance().fetchProcess(
        ProcessLoadCFV.class, ownerKeys);
    if (process != null) {
      dd.put("domain_uuid", uuid);
      dd.put("process_uuid", process.getUuid());
      dd.setWorkingTemplate(TEMPLATE_LOADCFV_DOING);
      return ActionConstants.APPLICATIONFRAME;
    }

    if ("1".equals(step)) {
      BDomain domain = getBDomainMgr().loadDomain(uuid);
      if (domain == null)
        throw new Exception("指定的组织不存在。");
      dd.put("domain", domain);

      List<BCartFunctionView> validCFVs = getValidCFVs(domain);
      dd.put("validCFVs", validCFVs);

      dd.setWorkingTemplate(TEMPLATE_LOADCFV_1);

    } else if ("2".equals(step)) {
      BDomain domain = getBDomainMgr().loadDomain(uuid);
      if (domain == null)
        throw new Exception("指定的" + CDomain.CAPTION_CLASS + "不存在。");
      dd.put("domain", domain);
      String loadCFVUuid = (String) dd.getFormValue("cfv_uuid");
      if (loadCFVUuid == null)
        throw new Exception("请选择一个" + CCartFunctionView.CAPTION_CLASS + "。");
      List<BCartFunctionView> loadCFVs = getBDomainMgr().analyseLoadingCFVs(loadCFVUuid,
          domain.getUuid());
      dd.put("loadCFVs", loadCFVs);

      dd.setWorkingTemplate(TEMPLATE_LOADCFV_2);

    } else if ("done".equals(step)) {
      debugLogger.debug("loadFuncView: Step 1");
      String strOca = (String) dd.getFormValue("domain_oca");
      if (strOca == null)
        throw new Exception("缺少必须的参数domain_oca。");
      long oca = (new Long(strOca)).longValue();
      String loadCFVUuid = (String) dd.getFormValue("cfv_uuid");
      if (loadCFVUuid == null)
        throw new Exception("请选择一个" + CCartFunctionView.CAPTION_CLASS + "。");

      debugLogger.debug("loadFuncView: Step 2");
      BDomain domain = getBDomainMgr().loadDomain(uuid);
      if (domain == null)
        throw new Exception("指定的" + CDomain.CAPTION_CLASS + "不存在。");
      BCartFunctionView cfv = getBCartMgr().getFunctionView(loadCFVUuid);
      if (cfv == null)
        throw new Exception("指定的" + CCartFunctionView.CAPTION_CLASS + "不存在。");
      logger.info(EVENT_LOADCFV, CDomain.CAPTION_CLASS + ":" + domain.getNameCode() + "<br>"
          + CCartFunctionView.CAPTION_CLASS + ":" + cfv.getGlobalCaption());

      debugLogger.debug("loadFuncView: Step 3");
      process = new ProcessLoadCFV();
      process.setOwnerKeys(ownerKeys);
      process.setDomainUuid(uuid);
      process.setDomainOca(oca);
      process.setTargetCFVUuid(loadCFVUuid);
      process.setOperator(this.getCurrentUser());
      debugLogger.debug("loadFuncView: Step 4");
      BackProcessPool.getInstance().put(process);
      debugLogger.debug("loadFuncView: Step 5");
      process.start();

      debugLogger.debug("loadFuncView: Step 6");
      dd.put("domain_uuid", uuid);
      dd.put("process_uuid", process.getUuid());
      dd.setWorkingTemplate(TEMPLATE_LOADCFV_DOING);
    }

    return ActionConstants.APPLICATIONFRAME;
  }

  public String unloadFuncView() throws Exception {
    String step = (String) dd.getFormValue("step");
    if (step == null)
      step = "1";
    String uuid = (String) dd.getFormValue("domain_uuid");
    if (uuid == null)
      throw new Exception("缺少必须的参数domain_uuid。");

    String[] ownerKeys = new String[] {
        this.getCurrentUser().getUuid(), uuid };
    ProcessUnloadCFV process = (ProcessUnloadCFV) BackProcessPool.getInstance().fetchProcess(
        ProcessUnloadCFV.class, ownerKeys);
    if (process != null) {
      dd.put("domain_uuid", uuid);
      dd.put("process_uuid", process.getUuid());
      dd.setWorkingTemplate(TEMPLATE_UNLOADCFV_DOING);
      return ActionConstants.APPLICATIONFRAME;
    }

    if ("1".equals(step)) {
      BDomain domain = getBDomainMgr().loadDomain(uuid);
      if (domain == null)
        throw new Exception("指定的组织不存在。");
      dd.put("domain", domain);
      String unloadCFVUuid = (String) dd.getFormValue("cfv_uuid");
      if (unloadCFVUuid == null)
        throw new Exception("请选择一个" + CCartFunctionView.CAPTION_CLASS + "。");
      List<BCartFunctionView> unloadCFVs = getBDomainMgr().analyseUnloadingCFVs(unloadCFVUuid,
          domain.getUuid());
      dd.put("unloadCFVs", unloadCFVs);

      dd.setWorkingTemplate(TEMPLATE_UNLOADCFV_1);

    } else if ("done".equals(step)) {
      debugLogger.debug("unloadFuncView: Step 1");
      String strOca = (String) dd.getFormValue("domain_oca");
      if (strOca == null)
        throw new Exception("缺少必须的参数domain_oca。");
      long oca = (new Long(strOca)).longValue();
      String unloadCFVUuid = (String) dd.getFormValue("cfv_uuid");
      if (unloadCFVUuid == null)
        throw new Exception("请选择一个" + CCartFunctionView.CAPTION_CLASS + "。");

      debugLogger.debug("unloadFuncView: Step 2");
      BDomain domain = getBDomainMgr().loadDomain(uuid);
      if (domain == null)
        throw new Exception("指定的" + CDomain.CAPTION_CLASS + "不存在。");
      BCartFunctionView cfv = getBCartMgr().getFunctionView(unloadCFVUuid);
      if (cfv == null)
        throw new Exception("指定的" + CCartFunctionView.CAPTION_CLASS + "不存在。");
      logger.info(EVENT_UNLOADCFV, CDomain.CAPTION_CLASS + ":" + domain.getNameCode() + "<br>"
          + CCartFunctionView.CAPTION_CLASS + ":" + cfv.getGlobalCaption());

      debugLogger.debug("unloadFuncView: Step 3");
      process = new ProcessUnloadCFV();
      process.setOwnerKeys(ownerKeys);
      process.setDomainUuid(uuid);
      process.setDomainOca(oca);
      process.setTargetCFVUuid(unloadCFVUuid);
      process.setOperator(this.getCurrentUser());
      debugLogger.debug("unloadFuncView: Step 4");
      BackProcessPool.getInstance().put(process);
      debugLogger.debug("unloadFuncView: Step 5");
      process.start();

      debugLogger.debug("unloadFuncView: Step 6");
      dd.put("domain_uuid", uuid);
      dd.put("process_uuid", process.getUuid());
      dd.setWorkingTemplate(TEMPLATE_UNLOADCFV_DOING);
    }

    return ActionConstants.APPLICATIONFRAME;
  }

  /**
   * 用于汇总页面用户列表的查询。
   * 
   * @param bsq
   * @param pageSize
   * @param page
   * @return
   * @throws Exception
   */
  public BResultPage queryList(BSQLSubquery bsq, int pageSize, int page) throws Exception {
    try {
      addForceFilter(bsq);
      return super.query(bsq, pageSize, page);
    } catch (Exception e) {
      this.reportError("", e);
      throw e;
    }
  }

  public BResultPage query(BSQLSubquery bsq, int pageSize, int page) throws Exception {
    try {
      addForceFilter(bsq);
      return super.query(bsq, pageSize, page);
    } catch (Exception e) {
      this.reportError("", e);
      throw e;
    }
  }

  public DomainEntriesValidation getEntriesValidation(String domainUuid, String domainCode)
      throws Exception {
    try {
      DomainEntriesValidation ev = new DomainEntriesValidation();

      if (domainCode.equals(CDomain.VALUE_ID_ROOT))
        ev.setOrganization(Boolean.FALSE);

      ViewUser viewUser = new ViewUser();
      viewUser.init(dd);
      String permUsers = viewUser.getPermission(ViewUser.FUNCTION_VIEW, domainUuid, Boolean.FALSE);
      if (permUsers != null && !this.getCurrentUser().hasPermission(permUsers))
        ev.setUsers(Boolean.FALSE);

      ViewRole viewRole = new ViewRole();
      viewRole.init(dd);
      String permRoles = viewRole.getPermission(ViewRole.FUNCTION_VIEW, domainUuid, Boolean.FALSE);
      if (!this.getCurrentUser().hasPermission(permRoles))
        ev.setRoles(Boolean.FALSE);

      // TODO
      return ev;
    } catch (Exception e) {
      this.reportError("", e);
      throw e;
    }
  }

  /**
   * 根据功能等信息取得权限ID。
   * 
   * @param functionName
   *          功能名，取值为类似“FUNCTION_*”的常量。
   * @param domainUuid
   *          指定访问域的uuid。
   * @param isRecycle
   *          是否是回收站
   * @return 返回权限ID，若没有权限对应则返回null。
   * @throws BusinessException
   * @throws HibernateException
   */
  public abstract String getPermission(String functionName, String domainUuid, Boolean isRecycle)
      throws BusinessException, HibernateException;

  /**
   * 根据功能等信息取得权限ID。
   * 
   * @param functionName
   *          功能名，取值为类似“FUNCTION_*”的常量。
   * @param relationship
   *          指定访问域的uuid。
   * @param isRecycle
   *          是否是回收站
   * @return 返回权限ID，若没有权限对应则返回null。
   * @throws BusinessException
   * @throws HibernateException
   */
  public abstract String getPermission(String functionName, int relationship, Boolean isRecycle)
      throws BusinessException, HibernateException;

  /**
   * 添加对用户的强制筛选条件。
   * 
   * @param bsq
   */
  protected abstract void addForceFilter(BSQLSubquery bsq) throws BusinessException;

  /**
   * 根据当前指定访问的域和是否是回收站，选择相应的权限放到dd中，以便页面使用。<br>
   * 各权限对应dd中的key见下表：<br> - "permissionView": 查看权<br> -
   * "permissionAnotherView": 另一个查看权，若当前显示正常数据，则代表回收站查看权；若当前在回收站，则代表是否有正常查看权。
   * 
   * @param isRecycle
   * @throws BusinessException
   */
  protected abstract void putFormPermissions(Boolean isRecycle) throws BusinessException;

  private IBDomainMgr bdmMgr = null;
  private IDomainMgr dmMgr = null;
  private IBCartridgeMgr bcartMgr = null;

  protected IBDomainMgr getBDomainMgr() throws BusinessException {
    if (bdmMgr == null)
      bdmMgr = (IBDomainMgr) NamingMgr.getInstance().lookupMgr(IBDomainMgr.class);
    return bdmMgr;
  }

  private IDomainMgr getDomainMgr() throws BusinessException {
    if (dmMgr == null)
      dmMgr = (IDomainMgr) NamingMgr.getInstance().lookupMgr(IDomainMgr.class);
    return dmMgr;
  }

  private IBCartridgeMgr getBCartMgr() throws BusinessException {
    if (bcartMgr == null)
      bcartMgr = (IBCartridgeMgr) NamingMgr.getInstance().lookupMgr(IBCartridgeMgr.class);
    return bcartMgr;
  }

  private DomainFilter getFormFilter() throws Exception {
    DomainFilter filter = new DomainFilter();
    filter.setCodeLike((String) dd.getFormValue("filter_codeLike"));
    filter.setNameLike((String) dd.getFormValue("filter_nameLike"));
    return filter;
  }

  private String showList(DomainFilter filter, Boolean isRecycle) throws Exception {
    dd.put("filter", filter);
    dd.put("isRecycle", isRecycle);
    this.putFormPermissions(isRecycle);
    dd.setWorkingTemplate(TEMPLATE_LIST);
    return ActionConstants.APPLICATIONFRAME;
  }

  private String showDetail(BDomain domain, String formState) throws Exception {
    dd.put("domain", domain);

    IPermissionMgr permMgr = (IPermissionMgr) NamingMgr.getInstance().lookupMgr(
        IPermissionMgr.class);
    dd.put("am", permMgr.createFieldsAccessMode(getCurrentUser(), CDomain.class));

    Boolean isRecycle = CDomain.VALUE_STATE_DELETED.equals(domain.getState()) ? Boolean.TRUE
        : Boolean.FALSE;
    this.putFormPermissions(isRecycle);
    dd.putFormValue(JspLib.ID_FORMSTATE, formState);
    dd.setWorkingTemplate(TEMPLATE_VIEW);
    ViewEntityLogs.preloadJSP(dd, domain.getUuid(), CDomain.STATEMAP);
    return ActionConstants.APPLICATIONFRAME;
  }

  private List<BCartFunctionView> getValidCFVs(BDomain domain) throws BusinessException,
      HibernateException {
    List<BCartFunctionView> result = new ArrayList();
    IDomain pdomain = getDomainMgr().getDomain(domain.getUuid());
    List<SCartFunctionView> loadedCFVs = getBDomainMgr().getCFVsByDomain(domain.getUuid());

    List<BCartridge> carts = getBCartMgr().getAllCartridges();
    for (int i = 0; i < carts.size(); i++) {
      BCartridge cart = carts.get(i);
      for (int j = 0; j < cart.getFunctionViews().size(); j++) {
        BCartFunctionView cfv = cart.getFunctionViews().get(j);
        if (!cfv.canLoadToDomain(pdomain))
          continue;
        if (cfv.getIsAbstract().booleanValue())
          continue;

        boolean loaded = false;
        for (int k = 0; k < loadedCFVs.size(); k++)
          if (cfv.getUuid().equals(loadedCFVs.get(k).getUuid())) {
            loaded = true;
            break;
          }
        if (loaded)
          continue;

        result.add(cfv);
      }
    }
    return result;
  }
}
